home *** CD-ROM | disk | FTP | other *** search
- #if !COMPILER
- /*
- * File: imisc.r
- * Contents: field, mkrec, limit, llist, bscan, escan
- */
-
- /*
- * x.y - access field y of record x.
- */
-
- LibDcl(field,2,".")
- {
- register word fnum;
- register struct b_record *rp;
- register dptr dp;
-
- extern word *ftabp, *records;
-
- #if MACINTOSH
- #if MPW
- /* #pragma unused(nargs) */
- #endif /* MPW */
- #endif /* MACINTOSH */
-
- Deref(Arg1);
-
- /*
- * Arg1 must be a record and Arg2 must be a field number.
- */
- if (!is:record(Arg1))
- RunErr(107, &Arg1);
-
- /*
- * Map the field number into a field number for the record x.
- */
- rp = (struct b_record *) BlkLoc(Arg1);
-
-
- fnum = ftabp[IntVal(Arg2) * *records + rp->recdesc->proc.recnum - 1];
- /*
- * If fnum < 0, x doesn't contain the specified field.
- */
- if (fnum < 0)
- RunErr(207, &Arg1);
-
- /*
- * Return a pointer to the descriptor for the appropriate field.
- */
- dp = &rp->fields[fnum];
- Arg0.dword = D_Var + ((word *)dp - (word *)rp);
- VarLoc(Arg0) = (dptr)rp;
- Return;
- }
-
-
- /*
- * mkrec - create a record.
- */
-
- LibDcl(mkrec,-1,"mkrec")
- {
- register int i;
- register struct b_proc *bp;
- register struct b_record *rp;
-
- /*
- * Be sure that call is from a procedure.
- */
-
- /*
- * Get a pointer to the record constructor procedure and allocate
- * a record with the appropriate number of fields.
- */
- bp = (struct b_proc *) BlkLoc(Arg0);
- Protect(rp = alcrecd((int)bp->nfields, (union block *)bp), RunErr(0,NULL));
-
- /*
- * Set all fields in the new record to null value.
- */
- for (i = (int)bp->nfields; i > nargs; i--)
- rp->fields[i-1] = nulldesc;
-
- /*
- * Assign each argument value to a record element and dereference it.
- */
- for ( ; i > 0; i--) {
- rp->fields[i-1] = Arg(i);
- Deref(rp->fields[i-1]);
- }
-
- ArgType(0) = D_Record;
- Arg0.vword.bptr = (union block *)rp;
- Return;
- }
-
- /*
- * limit - explicit limitation initialization.
- */
-
-
- LibDcl(limit,2,BackSlash)
- {
-
- C_integer tmp;
-
- #if MACINTOSH
- #if MPW
- /* #pragma unused(nargs) */
- #endif /* MPW */
- #endif /* MACINTOSH */
-
- /*
- * The limit is both passed and returned in Arg0. The limit must
- * be an integer. If the limit is 0, the expression being evaluated
- * fails. If the limit is < 0, it is an error. Note that the
- * result produced by limit is ultimately picked up by the lsusp
- * function.
- */
- Deref(Arg0);
-
- if (!cnv:C_integer(Arg0,tmp))
- RunErr(101, &Arg0);
- MakeInt(tmp,&Arg0);
-
- if (IntVal(Arg0) < 0)
- RunErr(205, &Arg0);
- if (IntVal(Arg0) == 0)
- Fail;
- Return;
- }
-
- /*
- * bscan - set &subject and &pos upon entry to a scanning expression.
- *
- * Arguments are:
- * Arg0 - new value for &subject
- * Arg1 - saved value of &subject
- * Arg2 - saved value of &pos
- *
- * A variable pointing to the saved &subject and &pos is returned to be
- * used by escan.
- */
-
- LibDcl(bscan,2,"?")
- {
- char sbuf[MaxCvtLen];
- int rc;
- struct pf_marker *cur_pfp;
-
- #if MACINTOSH
- #if MPW
- /* #pragma unused(nargs) */
- #endif /* MPW */
- #endif /* MACINTOSH */
-
- /*
- * Convert the new value for &subject to a string.
- */
- Deref(Arg0);
-
- if (!cnv:string(Arg0,Arg0))
- RunErr(103, &Arg0);
-
- /*
- * Establish a new &subject value and set &pos to 1.
- */
- k_subject = Arg0;
- k_pos = 1;
-
- /* If the saved scanning environment belongs to the current procedure
- * call, put a reference to it in the procedure frame.
- */
- if (pfp->pf_scan == NULL)
- pfp->pf_scan = &Arg1;
- cur_pfp = pfp;
-
- /*
- * Suspend with a variable pointing to the saved &subject and &pos.
- */
- ArgType(0) = D_Var;
- VarLoc(Arg0) = &Arg1;
-
- rc = interp(G_Csusp,cargp);
-
- if (pfp != cur_pfp)
- return rc;
-
- /*
- * Leaving scanning environment. Restore the old &subject and &pos values.
- */
- k_subject = Arg1;
- k_pos = IntVal(Arg2);
- if (pfp->pf_scan == &Arg1)
- pfp->pf_scan = NULL;
-
- if (rc == A_Resume)
- return A_Resume;
- else
- return rc;
-
- }
-
- /*
- * escan - restore &subject and &pos at the end of a scanning expression.
- *
- * Arguments:
- * Arg0 - variable pointing to old values of &subject and &pos
- * Arg1 - result of the scanning expression
- *
- * The two arguments are reversed, so that the result of the scanning
- * expression becomes the result of escan. This result is dereferenced
- * if it refers to &subject or &pos. Then the saved values of &subject
- * and &pos are exchanged with the current ones.
- *
- * Escan suspends once it has restored the old &subject; on failure
- * the new &subject and &pos are "unrestored", and the failure is
- * propagated into the using clause.
- */
-
- LibDcl(escan,1,"escan")
- {
- struct descrip tmp;
- int rc;
- struct pf_marker *cur_pfp;
-
- #if MACINTOSH
- #if MPW
- /* #pragma unused(nargs) */
- #endif /* MPW */
- #endif /* MACINTOSH */
-
- /*
- * Copy the result of the scanning expression into Arg0, which will
- * be the result of the scan.
- */
- tmp = Arg0;
- Arg0 = Arg1;
- Arg1 = tmp;
-
- /*
- * If the result of the scanning expression is &subject or &pos,
- * it is dereferenced. #%#% following is incorrect #%#%
- */
- /*if ((Arg0 == k_subject) ||
- (Arg0 == kywd_pos))
- Deref(Arg0); */
-
- /*
- * Swap new and old values of &subject
- */
- tmp = k_subject;
- k_subject = *VarLoc(Arg1);
- *VarLoc(Arg1) = tmp;
-
- /*
- * Swap new and old values of &pos
- */
- tmp = *(VarLoc(Arg1) + 1);
- IntVal(*(VarLoc(Arg1) + 1)) = k_pos;
- k_pos = IntVal(tmp);
-
- /*
- * If we are returning to the scanning environment of the current
- * procedure call, indicate that it is no longed in a saved state.
- */
- if (pfp->pf_scan == VarLoc(Arg1))
- pfp->pf_scan = NULL;
- cur_pfp = pfp;
-
- /*
- * Suspend the value of the scanning expression.
- */
-
- rc = interp(G_Csusp,cargp);
-
- if (pfp != cur_pfp)
- return rc;
-
- /*
- * Re-entering scanning environment, exchange the values of &subject
- * and &pos again
- */
- tmp = k_subject;
- k_subject = *VarLoc(Arg1);
- *VarLoc(Arg1) = tmp;
-
- tmp = *(VarLoc(Arg1) + 1);
- IntVal(*(VarLoc(Arg1) +1)) = k_pos;
- k_pos = IntVal(tmp);
-
- if (pfp->pf_scan == NULL)
- pfp->pf_scan = VarLoc(Arg1);
-
- if (rc == A_Resume)
- return A_Resume;
- else
- return rc;
- }
- #endif /* !COMPILER */
-